package _go

/*25. K 个一组翻转链表
难度
困难

1117

收藏

分享
切换为英文
接收动态
反馈
给你一个链表，每 k 个节点一组进行翻转，请你返回翻转后的链表。

k 是一个正整数，它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍，那么请将最后剩余的节点保持原有顺序。

进阶：

你可以设计一个只使用常数额外空间的算法来解决此问题吗？
你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换。


示例 1：


输入：head = [1,2,3,4,5], k = 2
输出：[2,1,4,3,5]
示例 2：


输入：head = [1,2,3,4,5], k = 3
输出：[3,2,1,4,5]
示例 3：

输入：head = [1,2,3,4,5], k = 1
输出：[1,2,3,4,5]
示例 4：

输入：head = [1], k = 1
输出：[1]
提示：

列表中节点的数量在范围 sz 内
1 <= sz <= 5000
0 <= Node.val <= 1000
1 <= k <= sz
*/
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseKGroup(head *ListNode, k int) *ListNode {
	//构建一个前序节点
	hair := &ListNode{Next: head}
	pre := hair

	for head != nil {
		//为节点就是前序节点
		tail := pre
		//向后遍历k次
		for i := 0; i < k; i++ {
			tail = tail.Next
			//tail为nil   直接返回就好 不够k次了
			if tail == nil {
				return hair.Next
			}
		}
		//记录尾节点  方便把返回的翻转好的串拼接上
		nex := tail.Next
		//翻转
		head, tail = myReverse(head, tail)
		//前序节点的next指向head
		pre.Next = head
		//尾节点指向原来的尾节点
		tail.Next = nex

		//前序节点向后移动 继续循环
		pre = tail
		head = tail.Next
	}
	return hair.Next
}

//原地翻转链表
func myReverse(head *ListNode, tail *ListNode) (*ListNode, *ListNode) {
	pre := tail.Next
	p := head
	for pre != tail {
		neat := p.Next
		p.Next = pre
		pre = p
		p = neat
	}
	return tail, head
}
